#ifndef XGE_XUNITTEST_XSINGLE_QUEUE_H_
#define XGE_XUNITTEST_XSINGLE_QUEUE_H_
#include "xge_common_config.h"
#include "xkillable_task.h"
#include "xworker_single_queue.h"
#include "xunit_test.h"
#include "xthread.h"
#include "xthread_delegate.h"
#include "xthread_manager.h"
#include "xassert.h"
#include "xsync.h"
#include "xtimer.h"
#include "xtask_memory_helper.h"
#include <stdio.h>

using xge::KillableTask;
using xge::xge_internal::WorkerQueue;
using xge::xge_internal::WorkerSingleQueue;
using xge::xge_internal::ThreadHandler;
using xge::xge_internal::ThreadHandlerPtr;
using xge::xge_internal::ThreadDelegate;
using xge::xge_internal::ThreadDelegatePtr;
using xge::xge_internal::ThreadManager;
using xge::String;
using xge::xge_internal::LoopTicking;
using xge::xge_internal::Timer;
using xge::xge_internal::TaskPtr;
using xge::xge_internal::TaskMemoryHelper;

namespace {
  class MyKillableTask : public KillableTask {
  public:

    virtual void Execute() {
      
      for( size_t i = 0 ; i < 20 ; ++i )
        printf("MyKillableTask.\n");
    }

    MyKillableTask( const String& name ) : KillableTask( REMOTE_BINDING , name ) {}
  };


  class MySingleQueueDispatcher : public ThreadDelegate {
  public:
    ThreadHandlerPtr thread_handler_;
    WorkerSingleQueue queue_;
    ThreadDelegatePtr thread_delegate_;
  public:
    virtual void ThreadMain() {
      queue_.Loop();
    }

    MySingleQueueDispatcher():thread_delegate_(this){
      thread_handler_ = ThreadManager::CreateXThread( 
        NULL,
        thread_delegate_,
        _xT("MyThread"),
        "single_thread"
        );
      XASSERT(!thread_handler_.Null());
    }
  };

  String Name(size_t block , size_t i ) {
    char_t buf[81];
    swprintf_s(buf,81,_xT("Name:%d,%d!!"),block,i);
    return String(buf);
  }
}

// Testing the fundemental function of this queue
UNIT_TEST(XSINGLE_QUEUE,Case1) {

  MySingleQueueDispatcher* stub = new MySingleQueueDispatcher();
  // Push 10 task into the queue and than kill one
  for( size_t i = 0 ; i < 10 ; ++i )
    stub->queue_.PushTask(
    TaskPtr( new MyKillableTask( Name(0,i) ) )
    );
  for( size_t i =0 ; i < 10 ; ++i ) {
    if( stub->queue_.KillTask( Name(0,i) ) ) {
      wprintf(_xT("Task Has Been Killed: %s\n"),Name(0,i).c_str());
    }
  }
  // push the whole
  Timer timer;
  timer.BeginTimerCounting();
  size_t iCountOut=0;
  WorkerQueue::TaskPtrList task_ptr_list;
  while(1) {
    ++iCountOut ;
    LoopTicking::UpdateLoopSync( timer.TimeDiff() );
    task_ptr_list.clear();
    for( size_t i = 0 ; i < 10 ; ++i ) {
      task_ptr_list.push_back( TaskPtr( new MyKillableTask( Name(iCountOut,i) ) ) );
    }
    stub->queue_.PushTask(&task_ptr_list);
    if( iCountOut == 10 ) {
      printf("end");
      stub->queue_.PostQuitSoon();
      stub->queue_.WaitWhenRelease();
      stub->thread_handler_->Join();
      break;
    }
  }
}




#endif// XGE_XUNITTEST_XSINGLE_QUEUE_H_